﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Utilities;
using TrenitaliaWP7.Resources;

namespace TrenitaliaWP7
{
    public class HTMLPaser
    {
        char[] html;
        public int pointer;
        
        public HTMLPaser(string html)
        {
            this.html = html.ToCharArray();
            pointer = 0;
            
            
        }
        

       
        protected bool GoToEndOfString(string searched)
        {
            if (searched.Length <= 0) return false;
            if (pointer >= html.Length) return false; //throw new InvalidRequestException();
            char[] s = searched.ToCharArray();

            for (int i = pointer; i < html.Length - s.Length; i++)
            {
                if (html[i] != s[0]) continue;
                bool found = true;
                for (int y = 1; y < s.Length; y++)
                    if (html[y + i] != s[y])
                    {
                        found = false;
                        break;
                    }
                if (found)
                {
                    //offset = i;
                    pointer = i + s.Length;
                    
                    return true;
                }
            }

            return false;
        }

        protected string GetTextUntilNextChar(char c)
        {
            string s = "";
            bool skip_spaces = true;
            for (int i = pointer; i < html.Length && html[i]!=c; i++)
            {
                if (!skip_spaces || (html[i] != ' ' && html[i] != '\n' && html[i] != '\r'))
                {
                    skip_spaces = false;
                    s += html[i];
                }
            }
            pointer += s.Length;
            return s.Replace("\t","").Replace("\r","").Replace("\n","").Trim();
        }

        protected int SearchNumberOfChanges()
        {
            char[] test = "<td rowspan=\"".ToCharArray();
            pointer++;
            for (int i = 0; i < test.Length; i++)
            {
                var a = html[pointer + i];
                if (html[pointer + i] != test[i])
                {
                    pointer += 4;
                    return 0;
                }
            }
            pointer += test.Length;
            var b = html[pointer];
            //int rows = Int32.Parse(""+a);
            int rows = Int32.Parse("" + b);
            pointer += 3;
            return rows;
        }

        protected bool IsStringPresentFromPointer(int startPointer, int stopPointer, string searched)
        {
            char[] s = searched.ToCharArray();
            //bool found = false;
            //for (int i = startPointer; i < html.Length - s.Length; i++)
            //{
            //    for (int y = 0; y < s.Length; y++)
            //    {
            //        if (html[i + y] != s[y])
            //            break;
            //    }
            //}
            //return found;

            //for (int i = pointer; i < html.Length - s.Length; i++)
            var stop = Math.Min(html.Length - s.Length, stopPointer);
            for (int i = startPointer; i < stop; i++)
            {
                if (html[i] != s[0]) continue;
                bool found = true;
                for (int y = 1; y < s.Length; y++)
                    if (html[y + i] != s[y])
                    {
                        found = false;
                        break;
                    }
                if (found)
                    return true;
            }
            return false;
        }

        protected bool IsStringPresentFromPointer(int startPointer, string searched)
        {
            char[] s = searched.ToCharArray();
            //bool found = false;
            //for (int i = startPointer; i < html.Length - s.Length; i++)
            //{
            //    for (int y = 0; y < s.Length; y++)
            //    {
            //        if (html[i + y] != s[y])
            //            break;
            //    }
            //}
            //return found;
            
            //for (int i = pointer; i < html.Length - s.Length; i++)
            for (int i = startPointer; i <= html.Length - s.Length; i++)
            {
                if (html[i] != s[0]) continue;
                bool found = true;
                for (int y = 1; y < s.Length; y++)
                    if (html[y + i] != s[y])
                    {
                        found = false;
                        break;
                    }
                if (found)
                    return true;
            }
            return false;
        }
        public bool IsStringPresentFromStart(string searched)
        {
            return IsStringPresentFromPointer(0, searched);
        }




        protected int GetStringPointer(string searched)
        {
            char[] s = searched.ToCharArray();
            for (int i = pointer; i < html.Length - s.Length; i++)
            {
                if (html[i] != s[0]) continue;
                bool found = true;
                for (int y = 1; y < s.Length; y++)
                    if (html[y + i] != s[y])
                    {
                        found = false;
                        break;
                    }
                if (found)
                    return i;
            }
            return -1;
        }

        public void setHTML(string html)
        {
            pointer = 0;
            this.html = html.ToCharArray();
        }        
    }

    public class DelayParser : HTMLPaser
    {
        public DelayParser(string html)
            : base(html)
        { }
        public string GetTrainDelay()
        {
            pointer = 0;
            GoToEndOfString("con ");
            var s = GetTextUntilNextChar(' ').Trim();
            int delay;
            if (Int32.TryParse(s, out delay))
            {
                if (delay <= 0)
                    return "";
                return "" + delay;
            }
            return "";
        }
        public string GetStatus()
        {
            pointer = 0;
            string status = "";
            if (!IsStringPresentFromStart("<td id=\"panRiepilogo\">"))
                return "";
            GoToEndOfString("<td id=\"panRiepilogo\">");
            GoToEndOfString("<span");
            GoToEndOfString(">");
            while (!IsStringPresentFromPointer(pointer, pointer + 10, "</span>"))
            {
                status += GetTextUntilNextChar('<') + " ";
                if(IsStringPresentFromPointer(pointer, pointer + 6, "<br />"))
                    GoToEndOfString("<br />");
            }
            return status;
        }
    }

    public class ResultParser : HTMLPaser
    {
        Result result;
        public ResultParser(string html)
            : base(html)
        {
            result = new Result();
        }

        public Result getResult()
        {
            if (!searchTrain("odd")) return result;
            if (!searchTrain("even")) return result;
            if (!searchTrain("odd")) return result;
            if (!searchTrain("even")) return result;
            if (!searchTrain("odd")) return result;

            /*
            if (!searchTrain("trow00")) return result;
            if (!searchTrain("trow00")) return result;
            if (!searchTrain("trow00")) return result;
            if (!searchTrain("trow00")) return result;
            if (!searchTrain("trow00")) return result;*/

            pointer = 0;
            GoToEndOfString("nppSolutionsUrl = \"");
            result.nextQuery = GetTextUntilNextChar('\"');
            return result;
        }

        //nuova grafica, da finire
        public bool searchTrain_nuovagrafica(string type)
        {

            if (!GoToEndOfString("<tr id=\"" + type + "\" >")) return false;

            GoToEndOfString("<strong> ");
            string from = GetTextUntilNextChar('<');

            GoToEndOfString("</strong><br />");
            string departure = GetTextUntilNextChar('<');

            int rows = SearchNumberOfChanges();

            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            string arrival = GetTextUntilNextChar('<');

            GoToEndOfString("<br>");
            string to = GetTextUntilNextChar('<');

            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            string duration = GetTextUntilNextChar('<');

            GoToEndOfString("</td><td>");

            var check = IsStringPresentFromPointer(pointer, pointer + 20, "&nbsp;");
            if (check)
            {
                GoToEndOfString("</td><td>");
            }

            string number = GetTextUntilNextChar('<');
            number = number.Trim();
            var c = number.Split(' ');
            if (c.Length > 1)
                for (int i = 0; i < c.Length; i++)
                {
                    short r;
                    if (Int16.TryParse(c[i], out r))
                    {
                        number = c[i];
                        break;
                    }
                }
            GoToEndOfString("</td><td><img alt=\"");

            string category = GetTextUntilNextChar('"');

            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            check = IsStringPresentFromPointer(pointer, pointer + 10, "&euro");
            string price1 = check ? GetTextUntilNextChar(' ') : "";
            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            check = IsStringPresentFromPointer(pointer, pointer + 10, "&euro");
            string price2 = check ? GetTextUntilNextChar(' ') : "";
            Details newTrain = new Details(from, to, departure, arrival, duration, number, category, price1, price2);

            for (int i = 0; i < rows - 1; i++)
            {
                GoToEndOfString("<tr class=\"" + type + "\">");
                GoToEndOfString("<td>");
                var hour = GetTextUntilNextChar('<');
                GoToEndOfString("<br>");
                var where = GetTextUntilNextChar('<');
                GoToEndOfString("</td><td>");
                var num = GetTextUntilNextChar('<');
                num = num.Trim();
                c = num.Split(' ');
                if (c.Length > 1)
                    for (int j = 0; j < c.Length; j++)
                    {
                        short r;
                        if (Int16.TryParse(c[j], out r))
                        {
                            num = c[j];
                            break;
                        }
                    }
                GoToEndOfString("</td><td><img alt=\"");
                var cat = GetTextUntilNextChar('"');
                newTrain.changes.Add(new Change(hour, where, cat, num));
            }



            result.solutions.Add(newTrain);
            return true;
        }

        public bool searchTrain(string type)
        {

            if (!GoToEndOfString("<tr class=\"" + type + "\">")) return false;
            int rows = SearchNumberOfChanges();
            string departure = GetTextUntilNextChar('<');

            GoToEndOfString("<br>");
            string from = GetTextUntilNextChar('<');

            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            string arrival = GetTextUntilNextChar('<');

            GoToEndOfString("<br>");
            string to = GetTextUntilNextChar('<');

            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            string duration = GetTextUntilNextChar('<');

            GoToEndOfString("</td><td>");

            var check = IsStringPresentFromPointer(pointer, pointer + 20, "&nbsp;");
            if (check)
            {
                GoToEndOfString("</td><td>");
            }

            string number = GetTextUntilNextChar('<');
            number = number.Trim();
            var c = number.Split(' ');
            if (c.Length > 1)
                for (int i = 0; i < c.Length; i++)
                {
                    short r;
                    if (Int16.TryParse(c[i], out r))
                    {
                        number = c[i];
                        break;
                    }
                }
            GoToEndOfString("</td><td><img alt=\"");

            string category = GetTextUntilNextChar('"');

            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            check = IsStringPresentFromPointer(pointer, pointer + 10, "&euro");
            string price1 = check ? GetTextUntilNextChar(' ') : "";
            GoToEndOfString(rows == 0 ? "</td><td>" : "</td><td rowspan=\"" + rows + "\">");
            check = IsStringPresentFromPointer(pointer, pointer + 10, "&euro");
            string price2 = check ? GetTextUntilNextChar(' ') : "";
            Details newTrain = new Details(from, to, departure, arrival, duration, number, category, price1, price2);

            for (int i = 0; i < rows - 1; i++)
            {
                GoToEndOfString("<tr class=\"" + type + "\">");
                GoToEndOfString("<td>");
                var hour = GetTextUntilNextChar('<');
                GoToEndOfString("<br>");
                var where = GetTextUntilNextChar('<');
                GoToEndOfString("</td><td>");
                var num = GetTextUntilNextChar('<');
                num = num.Trim();
                c = num.Split(' ');
                if (c.Length > 1)
                    for (int j = 0; j < c.Length; j++)
                    {
                        short r;
                        if (Int16.TryParse(c[j], out r))
                        {
                            num = c[j];
                            break;
                        }
                    }
                GoToEndOfString("</td><td><img alt=\"");
                var cat = GetTextUntilNextChar('"');
                newTrain.changes.Add(new Change(hour, where, cat, num));
            }



            result.solutions.Add(newTrain);
            return true;
        }

        public ArrayList<string> getFroms()
        {
            ArrayList<string> froms = new ArrayList<string>();

            //GoToEndOfString("<label for=\"partenza\">Da:</label><select name=\"stazin\" id=\"partenza\">");
            GoToEndOfString("<label for=\"partenza\">" + Strings.From +"</label><select name=\"stazin\" id=\"partenza\">");
            int endOfSearch = GetStringPointer("</option></select>");
            while (GoToEndOfString("<option value=\""))
            {
                if (pointer >= endOfSearch)
                    break;
                froms.Add(GetTextUntilNextChar('\"'));
            }

            return froms;
        }

        public ArrayList<string> getTos()
        {
            ArrayList<string> tos = new ArrayList<string>();

            //GoToEndOfString("<label for=\"arrivo\">A:</label><select name=\"stazout\" id=\"arrivo\">");
            GoToEndOfString("<label for=\"arrivo\">"+Strings.To + "</label><select name=\"stazout\" id=\"arrivo\">");
            int endOfSearch = GetStringPointer("</option></select>");
            while (GoToEndOfString("<option value=\""))
            {
                if (pointer >= endOfSearch)
                    break;
                tos.Add(GetTextUntilNextChar('\"'));
            }
            return tos;
        }
    }

    public class DetailsParser : HTMLPaser
    {
        public DetailsParser(string html)
            : base(html)
        {
        }
        public Train GetTrainDetail()
        {
            pointer = 0;
            Train t = new Train();

            GoToEndOfString("<h1>");
            string name = GetTextUntilNextChar('<');
            var n = name.Split(' ');
            t.number = n[n.Length - 1];

            while (GoToEndOfString("<h2>"))
            {
                t.stops.Add(GetTextUntilNextChar('<'));
                var c = IsStringPresentFromPointer(pointer, pointer + 150, "soppressa");
                if (c)
                    t.cancelled.Add(true);
                else
                    t.cancelled.Add(false);
                GoToEndOfString("<strong>");
                t.times.Add(GetTextUntilNextChar('<').Trim());
                GoToEndOfString("<strong>");
                t.real_times.Add(GetTextUntilNextChar('<').Trim());
                GoToEndOfString("Previsto:<br>");
                c = IsStringPresentFromPointer(pointer, pointer + 184, "<strong>");
                if (c)
                    GoToEndOfString("<strong>");
                t.binary.Add(GetTextUntilNextChar('<').Trim());
                c = IsStringPresentFromPointer(pointer, pointer + 184, "<strong>");
                if (c)
                    GoToEndOfString("<strong>");
                GoToEndOfString("Reale:<br>");
                t.real_binary.Add(GetTextUntilNextChar('<').Trim());
            }
            return t;
        }
    }

    public class LocationParser : HTMLPaser
    {
        public LocationParser(string html)
            : base(html)
        { }
        public string GetLocation()
        {
            GoToEndOfString("Valore:!");
            var s = GetTextUntilNextChar('!').Trim();

            return s;
        }
        public string GetLocation_yahoo()
        {
            GoToEndOfString("<city>");
            var s = GetTextUntilNextChar('<').Trim();
            
            return s;
        }
    }

}
